#!/usr/bin/env python3
"""
自动生成 git_pull_all 所有任务命令
"""

import os
import sys

def generate_tasks():
    """生成所有任务文件"""
    
    # 任务模板
    task_templates = {
        6: {
            "filename": "git_pull_all-task-6.py",
            "content": """#!/usr/bin/env python3
"""
任务 6: 创建结果报告器核心功能
文件: utils/result_reporter.py
实现 display_progress() 函数显示处理进度
实现 log_result() 函数记录单个仓库结果
实现 generate_summary() 函数生成汇总统计
"""

import time
from datetime import datetime
from typing import List, Dict, Any

class ResultReporter:
    """结果报告器"""
    
    def __init__(self, verbose: bool = False):
        """
        初始化结果报告器
        
        Args:
            verbose: 是否启用详细输出
        """
        self.verbose = verbose
        self.start_time = None
        self.processed_count = 0
        self.success_count = 0
        self.failed_count = 0
        self.skipped_count = 0
        self.results = []
    
    def start_processing(self, total_repos: int):
        """
        开始处理
        
        Args:
            total_repos: 仓库总数
        """
        self.start_time = datetime.now()
        self.processed_count = 0
        self.success_count = 0
        self.failed_count = 0
        self.skipped_count = 0
        self.results = []
        
        print(f"开始处理 {total_repos} 个 Git 仓库...")
        print("=" * 60)
    
    def display_progress(self, current_repo: str, repo_count: int, total_repos: int):
        """
        显示处理进度
        
        Args:
            current_repo: 当前处理的仓库
            repo_count: 当前仓库序号
            total_repos: 仓库总数
        """
        self.processed_count = repo_count
        
        # 计算进度百分比
        progress = (repo_count / total_repos) * 100
        
        # 显示进度条
        bar_length = 40
        filled_length = int(bar_length * repo_count // total_repos)
        bar = '█' * filled_length + '-' * (bar_length - filled_length)
        
        print(f"\\r进度: [{bar}] {progress:.1f}% ({repo_count}/{total_repos}) "
              f"处理: {current_repo}", end='', flush=True)
    
    def log_result(self, repo_path: str, status: str, output: str = "", error: str = ""):
        """
        记录单个仓库结果
        
        Args:
            repo_path: 仓库路径
            status: 状态 (success/failed/skipped)
            output: 输出信息
            error: 错误信息
        """
        # 更新计数器
        if status == "success":
            self.success_count += 1
        elif status == "failed":
            self.failed_count += 1
        elif status == "skipped":
            self.skipped_count += 1
        
        # 记录结果
        result = {
            "path": repo_path,
            "status": status,
            "output": output,
            "error": error,
            "timestamp": datetime.now().isoformat()
        }
        self.results.append(result)
        
        # 显示详细结果
        if self.verbose:
            print(f"\\n仓库: {repo_path}")
            print(f"状态: {status}")
            if output:
                print(f"输出: {output}")
            if error:
                print(f"错误: {error}")
            print("-" * 40)
    
    def generate_summary(self) -> Dict[str, Any]:
        """
        生成汇总统计
        
        Returns:
            Dict[str, Any]: 汇总信息
        """
        end_time = datetime.now()
        duration = end_time - self.start_time
        duration_seconds = duration.total_seconds()
        
        summary = {
            "total_repos": len(self.results),
            "processed_count": self.processed_count,
            "success_count": self.success_count,
            "failed_count": self.failed_count,
            "skipped_count": self.skipped_count,
            "duration_seconds": duration_seconds,
            "start_time": self.start_time.isoformat(),
            "end_time": end_time.isoformat(),
            "success_rate": (self.success_count / max(1, len(self.results))) * 100,
            "results": self.results
        }
        
        return summary
    
    def print_summary(self):
        """打印汇总报告"""
        summary = self.generate_summary()
        
        print("\\n" + "=" * 60)
        print("处理完成 - 汇总报告")
        print("=" * 60)
        print(f"总仓库数: {summary['total_repos']}")
        print(f"成功更新: {summary['success_count']}")
        print(f"更新失败: {summary['failed_count']}")
        print(f"跳过处理: {summary['skipped_count']}")
        print(f"成功率: {summary['success_rate']:.1f}%")
        print(f"总耗时: {summary['duration_seconds']:.2f} 秒")
        print(f"平均耗时: {summary['duration_seconds'] / max(1, summary['total_repos']):.2f} 秒/仓库")
        
        if summary['failed_count'] > 0:
            print("\\n失败的仓库:")
            for result in summary['results']:
                if result['status'] == 'failed':
                    print(f"  - {result['path']}: {result['error']}")
        
        print("=" * 60)

def test_result_reporter():
    """测试结果报告器"""
    print("测试结果报告器...")
    
    reporter = ResultReporter(verbose=True)
    
    # 开始处理
    reporter.start_processing(5)
    
    # 模拟处理过程
    test_repos = [
        ("/tmp/repo1", "success", "更新成功", ""),
        ("/tmp/repo2", "failed", "", "网络超时"),
        ("/tmp/repo3", "success", "更新成功", ""),
        ("/tmp/repo4", "skipped", "仓库不存在", ""),
        ("/tmp/repo5", "success", "更新成功", "")
    ]
    
    for i, (repo_path, status, output, error) in enumerate(test_repos, 1):
        reporter.display_progress(repo_path, i, 5)
        time.sleep(0.5)  # 模拟处理时间
        reporter.log_result(repo_path, status, output, error)
    
    print()  # 换行
    reporter.print_summary()

if __name__ == "__main__":
    test_result_reporter()
"""
        },
        7: {
            "filename": "git_pull_all-task-7.py",
            "content": """#!/usr/bin/env python3
"""
任务 7: 集成组件到 main.py
文件: main.py (继续修改)
导入所有核心组件和模型
实现 create_config() 函数创建配置对象
实现 setup_components() 函数初始化组件
"""

import sys
import os
from pathlib import Path

# 导入我们创建的模块
try:
    from models.git_repository import GitRepository
    from models.configuration import Configuration
    from utils.directory_scanner import DirectoryScanner
    from utils.git_executor import GitExecutor
    from utils.result_reporter import ResultReporter
except ImportError as e:
    print(f"错误：无法导入模块: {e}")
    print("请确保所有模块文件都在正确的位置")
    sys.exit(1)

def create_config(args) -> Configuration:
    """
    创建配置对象
    
    Args:
        args: 命令行参数对象
        
    Returns:
        Configuration: 配置对象
    """
    try:
        config = Configuration(
            root_directory=args.directory,
            include_patterns=args.include,
            exclude_patterns=args.exclude,
            verbose=args.verbose,
            dry_run=args.dry_run,
            timeout=args.timeout,
            max_workers=args.max_workers
        )
        
        if not config.is_valid:
            print(f"配置错误: {config.error_message}")
            return None
            
        return config
        
    except Exception as e:
        print(f"创建配置时发生错误: {str(e)}")
        return None

def setup_components(config: Configuration) -> tuple:
    """
    设置和初始化组件
    
    Args:
        config: 配置对象
        
    Returns:
        tuple: (scanner, executor, reporter) 组件元组
    """
    try:
        # 创建目录扫描器
        scanner = DirectoryScanner(max_depth=10)
        
        # 创建 Git 执行器
        executor = GitExecutor(
            timeout=config.timeout,
            verbose=config.verbose
        )
        
        # 创建结果报告器
        reporter = ResultReporter(verbose=config.verbose)
        
        return scanner, executor, reporter
        
    except Exception as e:
        print(f"设置组件时发生错误: {str(e)}")
        return None, None, None

def test_integration():
    """测试组件集成"""
    print("测试组件集成...")
    
    # 模拟命令行参数
    class MockArgs:
        def __init__(self):
            self.directory = "."
            self.include = []
            self.exclude = ["*/.git", "*/venv", "*/node_modules"]
            self.verbose = True
            self.dry_run = False
            self.timeout = 300
            self.max_workers = 4
    
    args = MockArgs()
    
    # 测试配置创建
    print("测试配置创建...")
    config = create_config(args)
    if config:
        print(f"配置创建成功: {config.get_summary()}")
    else:
        print("配置创建失败")
        return
    
    # 测试组件设置
    print("测试组件设置...")
    scanner, executor, reporter = setup_components(config)
    
    if scanner and executor and reporter:
        print("组件设置成功")
        print(f"扫描器类型: {type(scanner)}")
        print(f"执行器类型: {type(executor)}")
        print(f"报告器类型: {type(reporter)}")
    else:
        print("组件设置失败")
        return
    
    # 测试基本功能
    print("测试基本功能...")
    
    # 测试目录扫描
    git_repos = scanner.find_git_repositories(
        config.root_directory,
        config.include_patterns,
        config.exclude_patterns
    )
    print(f"找到 {len(git_repos)} 个 Git 仓库")
    
    # 测试 Git 执行器
    if git_repos:
        repo_path = git_repos[0]
        print(f"测试 Git 执行器: {repo_path}")
        
        # 检查仓库有效性
        is_valid = scanner.is_valid_git_repo(repo_path)
        print(f"仓库 {repo_path} 是否有效: {is_valid}")
        
        if is_valid:
            # 测试状态检查
            success, stdout, stderr = executor.execute_git_command(repo_path, ["status"])
            print(f"状态检查结果: 成功={success}, 输出={stdout.strip()}")
    
    # 测试结果报告器
    print("测试结果报告器...")
    reporter.start_processing(3)
    
    # 模拟处理过程
    test_repos = ["/tmp/repo1", "/tmp/repo2", "/tmp/repo3"]
    for i, repo_path in enumerate(test_repos, 1):
        reporter.display_progress(repo_path, i, 3)
        
        # 模拟不同的结果
        if i == 1:
            reporter.log_result(repo_path, "success", "更新成功")
        elif i == 2:
            reporter.log_result(repo_path, "failed", "", "网络超时")
        else:
            reporter.log_result(repo_path, "skipped", "仓库不存在")
    
    reporter.print_summary()

if __name__ == "__main__":
    test_integration()
"""
        },
        8: {
            "filename": "git_pull_all-task-8.py",
            "content": """#!/usr/bin/env python3
"""
任务 8: 实现 main.py 主执行流程
文件: main.py (继续修改)
实现 main() 函数的完整执行逻辑
添加异常处理和清理逻辑
实现 handle_errors() 函数处理全局错误
"""

import sys
import os
import traceback
from pathlib import Path

# 导入我们创建的模块
try:
    from models.git_repository import GitRepository
    from models.configuration import Configuration
    from utils.directory_scanner import DirectoryScanner
    from utils.git_executor import GitExecutor
    from utils.result_reporter import ResultReporter
except ImportError as e:
    print(f"错误：无法导入模块: {e}")
    sys.exit(1)

def handle_error(error: Exception, context: str = ""):
    """
    处理错误
    
    Args:
        error: 异常对象
        context: 错误上下文
    """
    error_type = type(error).__name__
    error_msg = str(error)
    
    if context:
        print(f"错误发生在 {context}: {error_type}: {error_msg}")
    else:
        print(f"错误: {error_type}: {error_msg}")
    
    # 如果是调试模式，打印完整的堆栈跟踪
    if os.environ.get("DEBUG", "false").lower() == "true":
        traceback.print_exc()

def main():
    """主执行函数"""
    try:
        # 导入参数解析函数
        from git_pull_all_task_3 import parse_arguments, validate_args
        
        # 解析命令行参数
        args = parse_arguments()
        
        # 验证参数
        if not validate_args(args):
            print("参数验证失败，请检查输入参数")
            sys.exit(1)
        
        print(f"git_pull_all - 批量更新 Git 仓库工具")
        print(f"扫描目录: {args.directory}")
        print(f"详细模式: {args.verbose}")
        print(f"预览模式: {args.dry_run}")
        print("-" * 60)
        
        # 创建配置
        config = Configuration(
            root_directory=args.directory,
            include_patterns=args.include,
            exclude_patterns=args.exclude,
            verbose=args.verbose,
            dry_run=args.dry_run,
            timeout=args.timeout,
            max_workers=args.max_workers
        )
        
        if not config.is_valid:
            print(f"配置错误: {config.error_message}")
            sys.exit(1)
        
        # 设置组件
        scanner = DirectoryScanner(max_depth=10)
        executor = GitExecutor(timeout=config.timeout, verbose=config.verbose)
        reporter = ResultReporter(verbose=config.verbose)
        
        # 开始处理
        print("开始扫描 Git 仓库...")
        
        # 查找 Git 仓库
        git_repos = scanner.find_git_repositories(
            config.root_directory,
            config.include_patterns,
            config.exclude_patterns
        )
        
        if not git_repos:
            print("未找到任何 Git 仓库")
            sys.exit(0)
        
        print(f"找到 {len(git_repos)} 个 Git 仓库")
        
        # 开始处理过程
        reporter.start_processing(len(git_repos))
        
        # 处理每个仓库
        for i, repo_path in enumerate(git_repos, 1):
            try:
                # 显示进度
                reporter.display_progress(repo_path, i, len(git_repos))
                
                # 检查仓库有效性
                if not scanner.is_valid_git_repo(repo_path):
                    reporter.log_result(repo_path, "skipped", "不是有效的 Git 仓库")
                    continue
                
                # 如果是预览模式，直接记录成功
                if config.dry_run:
                    reporter.log_result(repo_path, "success", "预览模式 - 跳过实际执行")
                    continue
                
                # 执行 git pull
                success, stdout, stderr = executor.pull_repository(repo_path)
                
                if success:
                    reporter.log_result(repo_path, "success", stdout)
                else:
                    reporter.log_result(repo_path, "failed", "", stderr)
                    
            except KeyboardInterrupt:
                print("\\n\\n用户中断操作")
                break
            except Exception as e:
                handle_error(e, f"处理仓库 {repo_path}")
                reporter.log_result(repo_path, "failed", "", str(e))
        
        # 打印汇总报告
        print()
        reporter.print_summary()
        
        # 根据结果设置退出码
        if reporter.failed_count > 0:
            print(f"警告：有 {reporter.failed_count} 个仓库更新失败")
            sys.exit(1)
        else:
            print("所有仓库更新成功")
            sys.exit(0)
            
    except KeyboardInterrupt:
        print("\\n操作被用户中断")
        sys.exit(1)
    except Exception as e:
        handle_error(e)
        sys.exit(1)

def main_entry():
    """主入口点"""
    try:
        main()
    except SystemExit:
        # 正常退出，不需要处理
        pass
    except KeyboardInterrupt:
        print("\\n程序被用户中断")
        sys.exit(1)
    except Exception as e:
        handle_error(e)
        sys.exit(1)

if __name__ == "__main__":
    main_entry()
"""
        },
        9: {
            "filename": "git_pull_all-task-9.py",
            "content": """#!/usr/bin/env python3
"""
任务 9: 创建 GitRepository 单元测试
文件: tests/test_git_repository.py
测试 GitRepository 类的初始化和属性设置
测试路径验证和仓库名称提取功能
测试错误处理和边界条件
"""

import unittest
import tempfile
import os
import shutil
from pathlib import Path

# 导入要测试的模块
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'models'))
from git_repository import GitRepository

class TestGitRepository(unittest.TestCase):
    """GitRepository 类的单元测试"""
    
    def setUp(self):
        """测试前准备"""
        self.test_dir = tempfile.mkdtemp()
        self.valid_repo_path = os.path.join(self.test_dir, "valid_repo")
        self.invalid_repo_path = os.path.join(self.test_dir, "invalid_repo")
        
        # 创建有效的 Git 仓库
        os.makedirs(self.valid_repo_path)
        subprocess.run(['git', 'init'], cwd=self.valid_repo_path, capture_output=True)
        
        # 创建无效的目录
        os.makedirs(self.invalid_repo_path)
        
    def tearDown(self):
        """测试后清理"""
        shutil.rmtree(self.test_dir)
    
    def test_init_valid_repository(self):
        """测试有效仓库的初始化"""
        repo = GitRepository(self.valid_repo_path)
        
        self.assertTrue(repo.is_valid)
        self.assertEqual(repo.path, self.valid_repo_path)
        self.assertEqual(repo.name, "valid_repo")
        self.assertEqual(repo.pull_status, "pending")
        self.assertEqual(repo.error_message, "")
    
    def test_init_invalid_repository(self):
        """测试无效仓库的初始化"""
        repo = GitRepository(self.invalid_repo_path)
        
        self.assertFalse(repo.is_valid)
        self.assertEqual(repo.path, self.invalid_repo_path)
        self.assertEqual(repo.name, "")
        self.assertEqual(repo.pull_status, "pending")
        self.assertNotEqual(repo.error_message, "")
    
    def test_init_nonexistent_path(self):
        """测试不存在的路径"""
        repo = GitRepository("/nonexistent/path")
        
        self.assertFalse(repo.is_valid)
        self.assertEqual(repo.path, "/nonexistent/path")
        self.assertEqual(repo.name, "")
        self.assertNotEqual(repo.error_message, "")
    
    def test_validate_path_valid(self):
        """测试有效路径验证"""
        repo = GitRepository(self.valid_repo_path)
        
        self.assertTrue(repo.is_valid)
        self.assertEqual(repo.error_message, "")
    
    def test_validate_path_invalid(self):
        """测试无效路径验证"""
        repo = GitRepository(self.invalid_repo_path)
        
        self.assertFalse(repo.is_valid)
        self.assertNotEqual(repo.error_message, "")
    
    def test_get_name_valid(self):
        """测试有效仓库名称提取"""
        repo = GitRepository(self.valid_repo_path)
        
        self.assertTrue(repo.is_valid)
        self.assertEqual(repo.name, "valid_repo")
    
    def test_get_name_invalid(self):
        """测试无效仓库名称提取"""
        repo = GitRepository(self.invalid_repo_path)
        
        self.assertFalse(repo.is_valid)
        self.assertEqual(repo.name, "")
    
    def test_update_status(self):
        """测试状态更新"""
        repo = GitRepository(self.valid_repo_path)
        
        # 更新为成功状态
        repo.update_status("success", "更新成功")
        
        self.assertEqual(repo.pull_status, "success")
        self.assertEqual(repo.error_message, "更新成功")
        self.assertNotEqual(repo.last_updated, "")
    
    def test_update_status_with_error(self):
        """测试带错误的状态更新"""
        repo = GitRepository(self.valid_repo_path)
        
        # 更新为失败状态
        repo.update_status("failed", "网络超时")
        
        self.assertEqual(repo.pull_status, "failed")
        self.assertEqual(repo.error_message, "网络超时")
    
    def test_string_representation(self):
        """测试字符串表示"""
        repo = GitRepository(self.valid_repo_path)
        
        str_repr = str(repo)
        self.assertIn("valid_repo", str_repr)
        self.assertIn("True", str_repr)
        self.assertIn("pending", str_repr)

def run_tests():
    """运行测试"""
    print("运行 GitRepository 单元测试...")
    
    # 创建测试套件
    suite = unittest.TestLoader().loadTestsFromTestCase(TestGitRepository)
    
    # 运行测试
    runner = unittest.TextTestRunner(verbosity=2)
    result = runner.run(suite)
    
    # 输出结果
    if result.wasSuccessful():
        print("\\n✅ 所有测试通过!")
        return True
    else:
        print(f"\\n❌ 测试失败: {len(result.failures)} 个失败, {len(result.errors)} 个错误")
        return False

if __name__ == "__main__":
    run_tests()
"""
        },
        10: {
            "filename": "git_pull_all-task-10.py",
            "content": """#!/usr/bin/env python3
"""
任务 10: 创建 Configuration 单元测试
文件: tests/test_configuration.py
测试 Configuration 类的配置验证
测试默认配置和参数处理
测试错误配置的异常处理
"""

import unittest
import tempfile
import os
import shutil
from pathlib import Path

# 导入要测试的模块
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'models'))
from configuration import Configuration

class TestConfiguration(unittest.TestCase):
    """Configuration 类的单元测试"""
    
    def setUp(self):
        """测试前准备"""
        self.test_dir = tempfile.mkdtemp()
        self.valid_dir = os.path.join(self.test_dir, "valid_dir")
        self.invalid_dir = os.path.join(self.test_dir, "invalid_dir")
        
        # 创建有效的目录
        os.makedirs(self.valid_dir)
        
    def tearDown(self):
        """测试后清理"""
        shutil.rmtree(self.test_dir)
    
    def test_init_valid_configuration(self):
        """测试有效配置的初始化"""
        config = Configuration(
            root_directory=self.valid_dir,
            include_patterns=["*project*"],
            exclude_patterns=["*test*"],
            verbose=True,
            dry_run=False
        )
        
        self.assertTrue(config.is_valid)
        self.assertEqual(config.root_directory, self.valid_dir)
        self.assertEqual(config.include_patterns, ["*project*"])
        self.assertEqual(config.exclude_patterns, ["*test*"])
        self.assertTrue(config.verbose)
        self.assertFalse(config.dry_run)
        self.assertEqual(config.error_message, "")
    
    def test_init_default_configuration(self):
        """测试默认配置的初始化"""
        config = Configuration(root_directory=self.valid_dir)
        
        self.assertTrue(config.is_valid)
        self.assertEqual(config.root_directory, self.valid_dir)
        self.assertEqual(config.include_patterns, [])
        self.assertEqual(config.exclude_patterns, [])
        self.assertFalse(config.verbose)
        self.assertFalse(config.dry_run)
    
    def test_init_invalid_directory(self):
        """测试无效目录的初始化"""
        config = Configuration(root_directory=self.invalid_dir)
        
        self.assertFalse(config.is_valid)
        self.assertNotEqual(config.error_message, "")
    
    def test_get_default_config(self):
        """测试获取默认配置"""
        config = Configuration.get_default_config()
        
        self.assertIsInstance(config, Configuration)
        self.assertTrue(config.is_valid)
        self.assertEqual(config.root_directory, ".")
        self.assertEqual(config.include_patterns, [])
        self.assertIsInstance(config.exclude_patterns, list)
        self.assertEqual(config.timeout, 300)
        self.assertEqual(config.max_workers, 4)
    
    def test_validate_config_valid(self):
        """测试有效配置验证"""
        config = Configuration(root_directory=self.valid_dir)
        
        self.assertTrue(config.is_valid)
        self.assertEqual(config.error_message, "")
    
    def test_validate_config_invalid_directory(self):
        """测试无效目录配置验证"""
        config = Configuration(root_directory="/nonexistent/path")
        
        self.assertFalse(config.is_valid)
        self.assertNotEqual(config.error_message, "")
    
    def test_validate_config_empty_directory(self):
        """测试空目录配置验证"""
        config = Configuration(root_directory="")
        
        self.assertFalse(config.is_valid)
        self.assertNotEqual(config.error_message, "")
    
    def test_should_include_repository_no_patterns(self):
        """测试无包含模式时的仓库包含逻辑"""
        config = Configuration(root_directory=self.valid_dir)
        
        # 没有包含模式时，应该包含所有仓库
        self.assertTrue(config.should_include_repository("/any/path"))
    
    def test_should_include_repository_with_patterns(self):
        """测试有包含模式时的仓库包含逻辑"""
        config = Configuration(
            root_directory=self.valid_dir,
            include_patterns=["*project*", "*repo*"]
        )
        
        # 匹配模式的路径应该被包含
        self.assertTrue(config.should_include_repository("/my_project"))
        self.assertTrue(config.should_include_repository("/my_repo"))
        # 不匹配模式的路径不应该被包含
        self.assertFalse(config.should_include_repository("/my_test"))
    
    def test_should_exclude_repository(self):
        """测试仓库排除逻辑"""
        config = Configuration(
            root_directory=self.valid_dir,
            exclude_patterns=["*test*", "*temp*"]
        )
        
        # 匹配排除模式的路径应该被排除
        self.assertTrue(config.should_exclude_repository("/my_test"))
        self.assertTrue(config.should_exclude_repository("/temp_folder"))
        # 不匹配排除模式的路径不应该被排除
        self.assertFalse(config.should_exclude_repository("/my_project"))
    
    def test_get_summary(self):
        """测试获取配置摘要"""
        config = Configuration(
            root_directory=self.valid_dir,
            include_patterns=["*project*"],
            verbose=True
        )
        
        summary = config.get_summary()
        
        self.assertIsInstance(summary, dict)
        self.assertEqual(summary["root_directory"], self.valid_dir)
        self.assertEqual(summary["include_patterns"], ["*project*"])
        self.assertTrue(summary["verbose"])
        self.assertTrue(summary["is_valid"])
        self.assertEqual(summary["error_message"], "")
    
    def test_timeout_validation(self):
        """测试超时时间验证"""
        # 有效超时时间
        config = Configuration(root_directory=self.valid_dir, timeout=300)
        self.assertTrue(config.is_valid)
        
        # 无效超时时间
        config = Configuration(root_directory=self.valid_dir, timeout=0)
        self.assertFalse(config.is_valid)
        self.assertIn("超时时间必须大于 0", config.error_message)
    
    def test_max_workers_validation(self):
        """测试最大并发数验证"""
        # 有效并发数
        config = Configuration(root_directory=self.valid_dir, max_workers=4)
        self.assertTrue(config.is_valid)
        
        # 无效并发数
        config = Configuration(root_directory=self.valid_dir, max_workers=0)
        self.assertFalse(config.is_valid)
        self.assertIn("最大并发数必须大于 0", config.error_message)

def run_tests():
    """运行测试"""
    print("运行 Configuration 单元测试...")
    
    # 创建测试套件
    suite = unittest.TestLoader().loadTestsFromTestCase(TestConfiguration)
    
    # 运行测试
    runner = unittest.TextTestRunner(verbosity=2)
    result = runner.run(suite)
    
    # 输出结果
    if result.wasSuccessful():
        print("\\n✅ 所有测试通过!")
        return True
    else:
        print(f"\\n❌ 测试失败: {len(result.failures)} 个失败, {len(result.errors)} 个错误")
        return False

if __name__ == "__main__":
    run_tests()
"""
        },
        11: {
            "filename": "git_pull_all-task-11.py",
            "content": """#!/usr/bin/env python3
"""
任务 11: 创建集成测试
文件: tests/test_git_pull_all.py
测试完整的工具流程和命令行选项
测试各种错误场景的处理
测试目录扫描和 Git 命令执行
"""

import unittest
import tempfile
import os
import shutil
import subprocess
from pathlib import Path

# 导入要测试的模块
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))

class TestGitPullAll(unittest.TestCase):
    """GitPullAll 工具的集成测试"""
    
    def setUp(self):
        """测试前准备"""
        self.test_dir = tempfile.mkdtemp()
        self.project_dir = os.path.join(self.test_dir, "projects")
        self.git_repos_dir = os.path.join(self.project_dir, "git_repos")
        
        # 创建项目结构
        os.makedirs(self.git_repos_dir)
        
        # 创建多个 Git 仓库
        self.repo_names = ["repo1", "repo2", "repo3"]
        self.repo_paths = []
        
        for repo_name in self.repo_names:
            repo_path = os.path.join(self.git_repos_dir, repo_name)
            os.makedirs(repo_path)
            
            # 初始化 Git 仓库
            subprocess.run(['git', 'init'], cwd=repo_path, capture_output=True)
            
            # 创建一个文件并提交
            with open(os.path.join(repo_path, "README.md"), "w") as f:
                f.write(f"# {repo_name}\\n")
            
            subprocess.run(['git', 'add', 'README.md'], cwd=repo_path, capture_output=True)
            subprocess.run(['git', 'commit', '-m', 'Initial commit'], cwd=repo_path, capture_output=True)
            
            self.repo_paths.append(repo_path)
    
    def tearDown(self):
        """测试后清理"""
        shutil.rmtree(self.test_dir)
    
    def test_directory_scanner_integration(self):
        """测试目录扫描器集成"""
        from utils.directory_scanner import DirectoryScanner
        
        scanner = DirectoryScanner(max_depth=5)
        
        # 扫描项目目录
        git_repos = scanner.scan_directory(self.project_dir)
        
        # 应该找到所有创建的仓库
        self.assertGreater(len(git_repos), 0)
        
        # 检查是否找到我们创建的仓库
        found_repos = []
        for repo_path in git_repos:
            repo_name = os.path.basename(repo_path)
            if repo_name in self.repo_names:
                found_repos.append(repo_name)
        
        self.assertEqual(len(found_repos), len(self.repo_names))
    
    def test_git_executor_integration(self):
        """测试 Git 执行器集成"""
        from utils.git_executor import GitExecutor
        
        executor = GitExecutor(timeout=30, verbose=False)
        
        # 测试一个仓库的状态检查
        if self.repo_paths:
            repo_path = self.repo_paths[0]
            success, stdout, stderr = executor.execute_git_command(repo_path, ["status"])
            
            # 即使仓库可能有问题，我们也应该得到结果
            self.assertIsInstance(success, bool)
            self.assertIsInstance(stdout, str)
            self.assertIsInstance(stderr, str)
    
    def test_configuration_integration(self):
        """测试配置集成"""
        from models.configuration import Configuration
        
        # 创建有效配置
        config = Configuration(
            root_directory=self.project_dir,
            include_patterns=["*git_repos*"],
            exclude_patterns=["*temp*"],
            verbose=True,
            dry_run=True  # 使用预览模式避免实际修改
        )
        
        self.assertTrue(config.is_valid)
        self.assertEqual(config.root_directory, self.project_dir)
        self.assertTrue(config.should_include_repository(self.git_repos_dir))
        self.assertFalse(config.should_exclude_repository(self.git_repos_dir))
    
    def test_full_workflow_integration(self):
        """测试完整工作流程"""
        # 导入组件
        from utils.directory_scanner import DirectoryScanner
        from utils.git_executor import GitExecutor
        from utils.result_reporter import ResultReporter
        from models.configuration import Configuration
        
        # 创建配置
        config = Configuration(
            root_directory=self.project_dir,
            include_patterns=["*git_repos*"],
            verbose=False,
            dry_run=True  # 预览模式
        )
        
        # 创建组件
        scanner = DirectoryScanner(max_depth=5)
        executor = GitExecutor(timeout=30, verbose=False)
        reporter = ResultReporter(verbose=False)
        
        # 查找仓库
        git_repos = scanner.scan_directory(
            config.root_directory,
            config.include_patterns,
            config.exclude_patterns
        )
        
        self.assertGreater(len(git_repos), 0)
        
        # 开始处理
        reporter.start_processing(len(git_repos))
        
        # 处理每个仓库
        for i, repo_path in enumerate(git_repos, 1):
            reporter.display_progress(repo_path, i, len(git_repos))
            
            # 检查仓库有效性
            if scanner.is_valid_git_repo(repo_path):
                if config.dry_run:
                    reporter.log_result(repo_path, "success", "预览模式")
                else:
                    # 在真实测试中，这里会执行 git pull
                    reporter.log_result(repo_path, "success", "模拟执行")
            else:
                reporter.log_result(repo_path, "skipped", "无效仓库")
        
        # 获取汇总
        summary = reporter.generate_summary()
        
        self.assertEqual(summary["total_repos"], len(git_repos))
        self.assertEqual(summary["success_count"] + summary["skipped_count"], len(git_repos))
        self.assertGreater(summary["duration_seconds"], 0)
    
    def test_error_handling_integration(self):
        """测试错误处理集成"""
        from utils.directory_scanner import DirectoryScanner
        
        scanner = DirectoryScanner(max_depth=5)
        
        # 测试无效目录
        invalid_repos = scanner.scan_directory("/nonexistent/path")
        self.assertEqual(len(invalid_repos), 0)
        
        # 测试权限问题（如果有的话）
        restricted_path = "/root"
        restricted_repos = scanner.scan_directory(restricted_path)
        # 即使没有权限，也应该优雅处理
        self.assertIsInstance(restricted_repos, list)

def run_tests():
    """运行集成测试"""
    print("运行 GitPullAll 集成测试...")
    
    # 创建测试套件
    suite = unittest.TestLoader().loadTestsFromTestCase(TestGitPullAll)
    
    # 运行测试
    runner = unittest.TextTestRunner(verbosity=2)
    result = runner.run(suite)
    
    # 输出结果
    if result.wasSuccessful():
        print("\\n✅ 所有集成测试通过!")
        return True
    else:
        print(f"\\n❌ 集成测试失败: {len(result.failures)} 个失败, {len(result.errors)} 个错误")
        return False

if __name__ == "__main__":
    run_tests()
"""
        },
        12: {
            "filename": "git_pull_all-task-12.py",
            "content": """#!/usr/bin/env python3
"""
任务 12: 更新项目配置
文件: pyproject.toml (修改现有)
添加测试依赖（pytest, pytest-cov）
配置脚本入口点（git-pull-all 命令）
配置测试命令和覆盖率报告
"""

import os
import toml
from pathlib import Path

def update_pyproject_toml():
    """更新 pyproject.toml 文件"""
    
    pyproject_path = Path("pyproject.toml")
    
    if not pyproject_path.exists():
        print("错误：pyproject.toml 文件不存在")
        return False
    
    try:
        # 读取现有的 pyproject.toml
        with open(pyproject_path, 'r', encoding='utf-8') as f:
            config = toml.load(f)
        
        # 确保 [project] 部分存在
        if 'project' not in config:
            config['project'] = {}
        
        # 更新项目信息
        config['project'].update({
            'name': 'cc-test-py',
            'version': '0.1.0',
            'description': 'Add your description here',
            'readme': 'README.md',
            'requires-python': '>=3.13'
        })
        
        # 添加脚本入口点
        if 'project' not in config:
            config['project'] = {}
        
        config['project']['scripts'] = {
            'git-pull-all': 'main:main_entry',
            'test-git-repository': 'tests.test_git_repository:run_tests',
            'test-configuration': 'tests.test_configuration:run_tests',
            'test-integration': 'tests.test_git_pull_all:run_tests',
            'test-all': 'python -m pytest tests/ -v'
        }
        
        # 添加测试依赖
        if 'project' not in config:
            config['project'] = {}
        if 'dependencies' not in config['project']:
            config['project']['dependencies'] = []
        
        # 添加测试工具依赖
        test_dependencies = [
            'pytest>=7.0.0',
            'pytest-cov>=4.0.0',
            'subprocess-run>=0.1.0'
        ]
        
        # 合并依赖（避免重复）
        existing_deps = config['project']['dependencies']
        for dep in test_dependencies:
            if dep not in existing_deps:
                existing_deps.append(dep)
        
        # 添加测试工具配置
        if 'tool' not in config:
            config['tool'] = {}
        
        config['tool']['pytest'] = {
            'testpaths': ['tests'],
            'python_files': ['test_*.py'],
            'python_classes': ['Test*'],
            'python_functions': ['test_*'],
            'addopts': [
                '--verbose',
                '--tb=short',
                '--cov=.',
                '--cov-report=html',
                '--cov-report=term-missing',
                '--cov-fail-under=80'
            ]
        }
        
        # 添加 uv 配置（如果存在）
        if 'tool' not in config:
            config['tool'] = {}
        
        if 'uv' not in config['tool']:
            config['tool']['uv'] = {}
        
        config['tool']['uv'].update({
            'index': [
                {'url': 'https://mirrors.aliyun.com/pypi/simple', 'default': True}
            ],
            'pip': {
                'index-url': 'https://repo.huaweicloud.com/repository/pypi/simple'
            }
        })
        
        # 写入更新后的配置
        with open(pyproject_path, 'w', encoding='utf-8') as f:
            toml.dump(config, f)
        
        print("✅ pyproject.toml 更新成功")
        print("添加的功能:")
        print("  - 脚本入口点: git-pull-all")
        print("  - 测试命令: test-git-repository, test-configuration, test-integration, test-all")
        print("  - 测试依赖: pytest, pytest-cov")
        print("  - 覆盖率配置: 最低 80% 覆盖率要求")
        
        return True
        
    except Exception as e:
        print(f"❌ 更新 pyproject.toml 失败: {str(e)}")
        return False

def show_updated_config():
    """显示更新后的配置"""
    pyproject_path = Path("pyproject.toml")
    
    if pyproject_path.exists():
        try:
            with open(pyproject_path, 'r', encoding='utf-8') as f:
                config = toml.load(f)
            
            print("\\n=== 更新后的 pyproject.toml 配置 ===")
            
            # 显示项目信息
            if 'project' in config:
                project = config['project']
                print(f"\\n项目信息:")
                print(f"  名称: {project.get('name', 'N/A')}")
                print(f"  版本: {project.get('version', 'N/A')}")
                print(f"  描述: {project.get('description', 'N/A')}")
                print(f"  Python 版本: {project.get('requires-python', 'N/A')}")
                
                # 显示脚本
                if 'scripts' in project:
                    print(f"\\n脚本命令:")
                    for script_name, script_command in project['scripts'].items():
                        print(f"  {script_name}: {script_command}")
                
                # 显示依赖
                if 'dependencies' in project:
                    print(f"\\n依赖:")
                    for dep in project['dependencies']:
                        print(f"  - {dep}")
            
            # 显示测试配置
            if 'tool' in config and 'pytest' in config['tool']:
                pytest_config = config['tool']['pytest']
                print(f"\\n测试配置:")
                print(f"  测试路径: {pytest_config.get('testpaths', 'N/A')}")
                print(f"  覆盖率要求: {pytest_config.get('addopts', [])}")
            
        except Exception as e:
            print(f"读取配置文件失败: {str(e)}")

def main():
    """主函数"""
    print("更新项目配置...")
    
    # 更新配置文件
    success = update_pyproject_toml()
    
    if success:
        # 显示更新后的配置
        show_updated_config()
        
        print("\\n=== 使用说明 ===")
        print("1. 安装依赖: pip install -e .")
        print("2. 运行测试: python git_pull_all-task-12.py")
        print("3. 使用工具: git-pull-all")
        print("4. 运行特定测试:")
        print("   - 测试 GitRepository: python tests/test_git_repository.py")
        print("   - 测试 Configuration: python tests/test_configuration.py")
        print("   - 测试集成: python tests/test_git_pull_all.py")
        print("   - 运行所有测试: pytest tests/ -v")
        
        return True
    else:
        return False

if __name__ == "__main__":
    main()
"""
        }
    }
    
    # 生成所有任务文件
    for task_num, task_info in task_templates.items():
        file_path = os.path.join(os.path.dirname(__file__), task_info['filename'])
        
        try:
            with open(file_path, 'w', encoding='utf-8') as f:
                f.write(task_info['content'])
            
            print(f"✅ 创建任务 {task_num}: {task_info['filename']}")
            
        except Exception as e:
            print(f"❌ 创建任务 {task_num} 失败: {str(e)}")
    
    print(f"\\n=== 任务命令生成完成 ===")
    print(f"总共生成了 {len(task_templates)} 个任务命令")
    print(f"\\n使用方法:")
    print(f"1. 逐个运行任务: python git_pull_all-task-{i}.py")
    print(f"2. 或者使用 generate_all_tasks.py 生成所有任务")

if __name__ == "__main__":
    generate_tasks()